package asm;

import org.objectweb.asm.*;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;

import static org.objectweb.asm.Opcodes.ASM5;

public class D_addMethod {
    public void addMethodByCoreAPI() throws Exception {
        ClassReader cr = Tool.getClassReader();
        ClassWriter cw = new ClassWriter(0);

        ClassVisitor cv = new ClassVisitor(ASM5, cw) {
            @Override
            public void visitEnd() {
                // visitEnd是访问类，访问的最后一个事件。在这个事件前添加变量就可以
                super.visitEnd();
                /**
                 * method的模板  public  <T>  List<String> hello(int i );
                 *
                 * Opcodes.ACC_PUBLIC   public 权限标志
                 * "hello" 变量名
                 * "(ILjava/lang/String;)V" 方法类型， （）代表参数:I int  'Ljava/lang/String;' String ; V代表返回值void
                 * null 泛型的标识
                 * null 异常数组
                 */
                MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "hello", "(ILjava/lang/String;)V", null, null);
                if (mv != null) {
                    mv.visitEnd();
                }
            }
        };
        //cr.accept(cv,ClassReader.SKIP_CODE|ClassReader.SKIP_DEBUG);
        cr.accept(cv, 0);
        byte[] bytesModifield = cw.toByteArray();

        Tool.save(this.getClass(), Application.class, bytesModifield);

    }

    public void addMethodByTreeAPI() throws Exception {
        ClassReader cr = Tool.getClassReader();
        ClassNode cn = new ClassNode();
        cr.accept(cn, ASM5);
        // 新的field
        MethodNode fn = new MethodNode(Opcodes.ACC_PUBLIC, "hello", "(ILjava/lang/String;)V", null, null);
        cn.methods.add(fn);

        // 打印
        ClassWriter cw = new ClassWriter(0);
        cn.accept(cw);
        byte[] bytesModified = cw.toByteArray();
        Tool.save(this.getClass(), Application.class, bytesModified);
    }

    public static void main(String[] args) throws Exception {
        new D_addMethod().addMethodByCoreAPI();
    }

}